﻿using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using System.Xml;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Windows.Forms;
using System.Reflection;
using System.IO.Compression;

namespace Xajhzwb.Components.Helper
{
    /// <summary>
    /// WebHelper
    /// </summary>
    public class WebHelper
    {
        private const string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 1.1.4322; InfoPath.2; MS-RTC LM 8)";

        #region StringSplit,StringJoin
        public static string[] StringSplit(string inputValue, string[] splitStr)
        {
            return inputValue.Split(splitStr, StringSplitOptions.RemoveEmptyEntries);
        }

        public static string StringJoin(string[] inputValue, string splitStr)
        {
            return StringJoin(inputValue, splitStr, false);
        }

        public static string StringJoin(string[] inputValue, string splitStr, bool IsReset)
        {
            string[] newValue = inputValue;
            if(IsReset)
            {
                for(int i = 0; i < inputValue.Length - 1; i++)
                {
                    newValue[i] = inputValue[i + 1];
                }
                inputValue[inputValue.Length - 1] = inputValue[0];
            }

            return String.Join(splitStr, inputValue);
        }
        #endregion

        #region DateRndName
        /// <summary>
        /// DateRndName
        /// </summary>
        /// <returns></returns>
        public static string DateRndName()
        {
            Random random = new Random();

            string s = System.DateTime.Now.ToString("yyyyMMdd_HHmmss");
            s += DateTime.Now.Millisecond.ToString();
            s += random.Next(100000000, 999999999).ToString();
            return s;
        }
        #endregion

        #region GetFileExtends
        /// <summary>
        /// GetFileExtends
        /// </summary>
        /// <param name="filename">文件名称</param>
        /// <returns></returns>
        public static string GetFileExtends(string filename)
        {
            return Path.GetExtension(filename);
        }
        #endregion

        #region GetHtmlSource
        public static string GetHtmlSource(string url, Encoding encoding, string cookie)
        {
            return GetHtmlSource(url, encoding, cookie, null, 0);
        }

        public static string GetHtmlSource(string url, Encoding encoding, string cookie, string userAgent, int timeout)
        {
            return GetHtmlSource(url, encoding, cookie, userAgent, timeout, null, null, null, null);
        }

        public static string GetHtmlSource(string url, Encoding encoding, string cookie, string userAgent, int timeout,
                                           string proxyServer, string proxyPort, string proxyUserName, string proxyPassWord)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            string strWebData = null;

            try
            {
                request = (HttpWebRequest)WebRequest.Create(url);

                if(userAgent != null)
                    request.UserAgent = userAgent;
                else
                    request.UserAgent = DefaultUserAgent;

                if(timeout != 0)
                    request.Timeout = timeout;
                else
                    request.Timeout = 20000;

                request.AllowAutoRedirect = false;
                if(cookie != null)
                    request.Headers["Cookie"] = cookie;

                // proxy set
                if(proxyServer != null && proxyPort != null)
                {
                    WebProxy proxy = new WebProxy();
                    proxy.Address = new Uri(proxyServer + ":" + proxyPort.ToString());
                    proxy.Credentials = new NetworkCredential(proxyUserName, proxyPassWord);
                    request.UseDefaultCredentials = true;
                    request.Proxy = proxy;
                }

                response = (HttpWebResponse)request.GetResponse();
                if(response.StatusCode == HttpStatusCode.OK && response.ContentLength < 1024 * 1024)
                {
                    System.Text.Encoding respenc = null;

                    if(encoding != null)
                    {
                        respenc = encoding;
                    }
                    else if(encoding == null)
                    {
                        if(!string.IsNullOrEmpty(response.ContentEncoding))
                        {
                            respenc = System.Text.Encoding.GetEncoding(response.ContentEncoding);
                        }
                        // encoding auto set
                        else if(!string.IsNullOrEmpty(response.CharacterSet))
                        {
                            if(string.Compare(response.CharacterSet, "ISO-8859-1", true,
                                              System.Globalization.CultureInfo.InvariantCulture) == 0)
                            {
                                respenc = System.Text.Encoding.GetEncoding("GB2312");
                            }
                            else
                            {
                                respenc = System.Text.Encoding.GetEncoding(response.CharacterSet);
                            }
                        }
                    }

                    if(response.ContentEncoding == "gzip")
                    {
                        GZipStream myGZip = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress);
                        System.IO.StreamReader reader;
                        reader = new System.IO.StreamReader(myGZip, encoding);
                        strWebData = reader.ReadToEnd();
                        reader.Close();
                        reader.Dispose();
                    }
                    else
                    {
                        System.IO.StreamReader reader;
                        reader = new System.IO.StreamReader(response.GetResponseStream(), encoding);
                        strWebData = reader.ReadToEnd();
                        reader.Close();
                        reader.Dispose();
                    }
                }
            }
            catch(Exception ex)
            {
                throw ex;
            }
            finally
            {
                if(response != null)
                {
                    response.Close();
                    response = null;
                }

                if(request != null)
                    request = null;
            }

            return strWebData;
        }
        #endregion

        #region ReplaceEnter
        /// <summary>
        /// ReplaceEnter
        /// </summary>
        /// <param name="htmlSource"></param>
        /// <returns></returns>
        public static string ReplaceEnter(string htmlSource)
        {
            string s = "";
            if(htmlSource == null || htmlSource == "")
                s = "";
            else
                s = htmlSource.Replace("\"", "");
            s = s.Replace("\r", "");
            s = s.Replace("\n", "");
            return s;
        }
        #endregion

        #region GetRegValue
        /// <summary>
        /// GetRegValue
        /// </summary>
        /// <param name="htmlSource"></param>
        /// <param name="regexString"></param>
        /// <returns></returns>
        public static string[] GetRegValue(string htmlSource, string regexString)
        {
            Regex r = new Regex(regexString, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.RightToLeft);

            MatchCollection m = r.Matches(htmlSource);
            string[] matchValue = new string[m.Count];
            for(int i = 0; i < m.Count; i++)
            {
                matchValue[i] = m[i].Value;
            }

            return matchValue;
        }

        /// <summary>
        /// GetRegValue
        /// </summary>
        /// <param name="htmlSource"></param>
        /// <param name="regexString"></param>
        /// <param name="groupKey"></param>
        /// <returns></returns>
        public static string[] GetRegValue(string htmlSource, string regexString, string groupKey)
        {
            try
            {
                string newRegexString = regexString.Replace(@"<%", @"(?<");
                newRegexString = newRegexString.Replace(@"%>", @">[^<].*?)");

                return GetRegValue(htmlSource, newRegexString, groupKey, true);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// GetRegValue
        /// </summary>
        /// <param name="htmlCode"></param>
        /// <param name="regexString"></param>
        /// <param name="groupKey"></param>
        /// <param name="rightToLeft"></param>
        /// <returns></returns>
        public static string[] GetRegValue(string htmlSource, string regexString, string groupKey, bool rightToLeft)
        {
            try
            {
                Regex regex;

                if(rightToLeft == true)
                {
                    regex = new Regex(regexString, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.RightToLeft);
                }
                else
                {
                    regex = new Regex(regexString, RegexOptions.IgnoreCase | RegexOptions.Singleline);
                }

                MatchCollection m = regex.Matches(htmlSource);
                string[] matchValue = new string[m.Count];
                for(int i = 0; i < m.Count; i++)
                {
                    matchValue[i] = m[i].Groups[groupKey].Value;
                }

                return matchValue;
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region RegReplace
        /// <summary>
        /// RegReplace
        /// </summary>
        /// <param name="RegValue"></param>
        /// <param name="regStart"></param>
        /// <param name="regEnd"></param>
        /// <returns></returns>
        public static string RegReplace(string regValue, string regStart, string regEnd)
        {
            string s = regValue;

            if(!String.IsNullOrEmpty(regValue))
            {
                if(!String.IsNullOrEmpty(regStart))
                {
                    s = s.Replace(regStart, "");
                }
                if(!String.IsNullOrEmpty(regEnd))
                {
                    s = s.Replace(regEnd, "");
                }
            }
            return s;
        }
        #endregion

        #region AddCookieWithCookieHead
        private static void AddCookieWithCookieHead(ref CookieCollection cookieCol, string cookieHead, string defaultDomain)
        {
            if(cookieCol == null)
                cookieCol = new CookieCollection();
            if(cookieHead == null)
                return;
            string[] ary = cookieHead.Split(';');
            for(int i = 0; i < ary.Length; i++)
            {
                Cookie ck = GetCookieFromString(ary[i].Trim(), defaultDomain);
                if(ck != null)
                {
                    cookieCol.Add(ck);
                }
            }
        }

        private static Cookie GetCookieFromString(string cookieString, string defaultDomain)
        {
            string[] ary = cookieString.Split(',');
            Hashtable hs = new Hashtable();
            for(int i = 0; i < ary.Length; i++)
            {
                string s = ary[i].Trim();
                int index = s.IndexOf("=");
                if(index > 0)
                {
                    hs.Add(s.Substring(0, index), s.Substring(index + 1));
                }
            }
            Cookie ck = new Cookie();
            foreach(object Key in hs.Keys)
            {
                if(Key.ToString() == "path")
                    ck.Path = hs[Key].ToString();

                else if(Key.ToString() == "expires")
                {
                    //ck.Expires=DateTime.Parse(hs[Key].ToString();
                }
                else if(Key.ToString() == "domain")
                    ck.Domain = hs[Key].ToString();
                else
                {
                    ck.Name = Key.ToString();
                    ck.Value = hs[Key].ToString();
                }
            }
            if(ck.Name == "")
                return null;
            if(ck.Domain == "")
                ck.Domain = defaultDomain;
            return ck;
        }
        #endregion

        #region GetHref
        /// <summary>
        /// GetHref
        /// </summary>
        /// <param name="htmlSource"></param>
        /// <returns></returns>
        public string GetHref(string htmlSource)
        {
            string MatchVale = "";
            string regexString = @"(h|H)(r|R)(e|E)(f|F) *= *('|"")?((\w|\\|\/|\.|:|-|_)+)[\S]*";
            foreach(Match m in Regex.Matches(htmlSource, regexString))
            {
                MatchVale += (m.Value).ToLower().Replace("href=", "").Trim() + "|";
            }
            return MatchVale;
        }
        #endregion

        #region GetImgSrc
        /// <summary>
        /// GetImgSrc
        /// </summary>
        /// <param name="HtmlCode"></param>
        /// <param name="imgHttp"></param>
        /// <returns></returns>
        public string GetImgSrc(string htmlSource, string imgHttp)
        {
            string MatchVale = "";
            string Reg = @"<img.+?>";
            foreach(Match m in Regex.Matches(htmlSource.ToLower(), Reg))
            {
                MatchVale += GetImg((m.Value).ToLower().Trim(), imgHttp) + "|";
            }

            return MatchVale;
        }

        public string GetImg(string imgString, string imgHttp)
        {
            string MatchVale = "";
            string Reg = @"src=.+\.(bmp|jpg|gif|png|)";
            foreach(Match m in Regex.Matches(imgString.ToLower(), Reg))
            {
                MatchVale += (m.Value).ToLower().Trim().Replace("src=", "");
            }
            if(MatchVale.IndexOf(".net") != -1 || MatchVale.IndexOf(".com") != -1 || MatchVale.IndexOf(".org") != -1 || MatchVale.IndexOf(".cn") != -1 || MatchVale.IndexOf(".cc") != -1 || MatchVale.IndexOf(".info") != -1 || MatchVale.IndexOf(".biz") != -1 || MatchVale.IndexOf(".tv") != -1)
                return (MatchVale);
            else
                return (imgHttp + MatchVale);
        }
        #endregion

        #region DownloadFile
        /// <summary>
        /// DownloadFile
        /// </summary>
        /// <param name="fileUrl"></param>
        /// <param name="fileSavePath"></param>
        /// <param name="cookie"></param>
        /// <returns></returns>
        public static long DownloadFile(string fileUrl, string fileSavePath, string cookie)
        {
            long fileLength = 0;
            HttpWebRequest request = HttpWebRequest.Create(fileUrl) as HttpWebRequest;

            if(cookie != null)
            {
                request.Headers["Cookie"] = cookie;
            }
            request.AllowAutoRedirect = true;

            HttpWebResponse res = request.GetResponse() as HttpWebResponse;
            System.IO.Stream stream = res.GetResponseStream();
            try
            {
                fileLength = res.ContentLength;

                byte[] b = new byte[512];

                int nReadSize = 0;
                nReadSize = stream.Read(b, 0, 512);

                System.IO.FileStream fs = System.IO.File.Create(fileSavePath);
                try
                {
                    while(nReadSize > 0)
                    {
                        fs.Write(b, 0, nReadSize);
                        nReadSize = stream.Read(b, 0, 512);
                    }
                }
                finally
                {
                    fs.Close();
                }
            }
            catch(Exception ex)
            {
                throw ex;
            }
            finally
            {
                res.Close();
                stream.Close();
            }

            return fileLength;
        }
        #endregion

        #region PostDownload
        /// <summary>
        /// PostDownload
        /// </summary>
        /// <param name="fileUrl"></param>
        /// <param name="fileSavePath"></param>
        /// <param name="requestData"></param>
        /// <param name="cookie"></param>
        /// <param name="userAgent"></param>
        /// <param name="timeout"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        public bool PostDownload(string fileUrl, string fileSavePath, RequestData requestData, string cookie, string userAgent, int timeout, out string file)
        {
            file = null;
            StreamReader reader = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            try
            {
                request = HttpWebRequest.Create(fileUrl) as HttpWebRequest;

                string postdata = requestData.GetData();
                request.Referer = fileUrl;
                request.AllowAutoRedirect = false;

                if(userAgent != null)
                    request.UserAgent = userAgent;
                else
                    request.UserAgent = DefaultUserAgent;

                if(timeout != 0)
                    request.Timeout = timeout;
                else
                    request.Timeout = 20000;

                if(cookie != null)
                    request.Headers["Cookie"] = cookie;

                Uri u = new Uri(fileUrl);

                if(postdata.Length > 0)
                {
                    request.ContentType = "application/x-www-form-urlencoded";
                    request.Method = "POST";

                    Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(postdata);
                    request.ContentLength = bytes.Length;

                    System.IO.Stream SW = request.GetRequestStream();
                    SW.Write(bytes, 0, bytes.Length);
                    SW.Close();
                }

                response = request.GetResponse() as HttpWebResponse;
                string des = response.Headers["Content-Disposition"].Trim();
                file = des.Substring(des.IndexOf("filename=") + 9);
                file = new Random().Next(100).ToString() + "/" + file;

                System.IO.Stream stream = response.GetResponseStream();
                try
                {
                    int Filelength = (int)response.ContentLength;

                    byte[] b = new byte[512];

                    int nReadSize = 0;
                    nReadSize = stream.Read(b, 0, 512);

                    System.IO.FileStream fs = System.IO.File.Create(fileSavePath + file);
                    try
                    {
                        while(nReadSize > 0)
                        {
                            fs.Write(b, 0, nReadSize);
                            nReadSize = stream.Read(b, 0, 512);
                        }
                    }
                    finally
                    {
                        fs.Close();
                    }
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    response.Close();
                    stream.Close();
                }
            }
            catch(Exception ex)
            {
                string x = ex.StackTrace;
            }
            finally
            {
                if(response != null)
                    response.Close();
            }
            return true;
        }
        #endregion

        

        #region FromBase64String
        public static string FromBase64String(string value)
        {
            byte[] bytes = Convert.FromBase64String(value);
            return Encoding.Default.GetString(bytes);
        }
        #endregion

        #region ToBase64String
        public static string ToBase64String(string value)
        {
            return Convert.ToBase64String(Encoding.Default.GetBytes(value));
        }
        #endregion

        #region ConvertUrl
        public static string ConvertUrl(string url)
        {
            string newUrl = url;

            try
            {
                // thunder
                if(url.ToLower().StartsWith("thunder://"))
                {
                    string str = url.Substring(10);
                    str = FromBase64String(str);
                    newUrl = str.Substring(2, str.Length - 4);
                }
                // flashget
                else if(url.ToLower().StartsWith("flashget://"))
                {
                    string str = url.Substring(11);
                    if(url.Contains("&"))
                    {
                        url = url.Substring(0, url.IndexOf("&"));
                    }
                    str = FromBase64String(str);

                    newUrl = str.Substring(10, str.Length - 20);
                }
                // qqdl
                else if(url.ToLower().StartsWith("qqdl://"))
                {
                    string str = url.Substring(7);
                    str = FromBase64String(str);
                    newUrl = str.Substring(0, str.Length);
                }
            }
            catch(Exception)
            {

            }

            return newUrl;
        }
        #endregion

        #region GetDefaultUserAgent
        /// <summary>
        /// 一个很BT的获取IE默认UserAgent的方法
        /// </summary>
        public static string GetDefaultUserAgent()
        {
            WebBrowser wb = new WebBrowser();
            wb.Navigate("about:blank");
            while (wb.IsBusy) Application.DoEvents();
            object window = wb.Document.Window.DomWindow;
            Type wt = window.GetType();
            object navigator = wt.InvokeMember("navigator", BindingFlags.GetProperty,
                null, window, new object[] { });
            Type nt = navigator.GetType();
            object userAgent = nt.InvokeMember("userAgent", BindingFlags.GetProperty,
                null, navigator, new object[] { });
            return userAgent.ToString();
        }
        #endregion

        public static string RegexReplaceTrans(string str)
        {
            if(str == "" || str == null)
                return "";

            string conStr = "";
            if(Regex.IsMatch(str, @"[\$\*\[\]\?\\\(\)]"))
            {
                Regex re = new Regex(@"\\", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\\");
                re = null;

                re = new Regex(@"\$", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\$");
                re = null;

                //re = new Regex(@"\.", RegexOptions.IgnoreCase);
                //str = re.Replace(str, @"\.");
                //re = null;

                re = new Regex(@"\*", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\*");
                re = null;

                re = new Regex(@"\[", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\[");
                re = null;

                re = new Regex(@"\]", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\]");
                re = null;

                re = new Regex(@"\?", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\?");
                re = null;

                re = new Regex(@"\(", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\(");
                re = null;

                re = new Regex(@"\)", RegexOptions.IgnoreCase);
                str = re.Replace(str, @"\)");
                re = null;

                conStr = str;

            }
            else
            {
                conStr = str;
            }
            return conStr;
        }


        #region Request
        public string Request(string requestUrl, string cookie, string userAgent, int timeout)
        {
            StreamReader reader = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;

            try
            {
                if(Regex.IsMatch(requestUrl, @"<POST>.*</POST>", RegexOptions.IgnoreCase))
                {
                    request = (HttpWebRequest)WebRequest.Create(@requestUrl.Substring(0, requestUrl.IndexOf("<POST>")));
                }
                else
                {
                    request = (HttpWebRequest)WebRequest.Create(@requestUrl);
                }

                Match a = Regex.Match(requestUrl, @"(http://).[^/]*[?=/]", RegexOptions.IgnoreCase);
                request.Referer = a.Groups[0].Value.ToString();

                request.AllowAutoRedirect = false;

                if(!string.IsNullOrEmpty(userAgent))
                {
                    request.UserAgent = userAgent;
                }
                else
                {
                    request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; Maxthon; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
                }

                if(timeout != 0)
                {
                    request.Timeout = timeout;
                }
                else
                {
                    request.Timeout = 20000;
                }

                if(!string.IsNullOrEmpty(cookie))
                {
                    CookieContainer cookieCon = new CookieContainer();
                    CookieCollection cl = new CookieCollection();
                    foreach(string sc in cookie.Split(';'))
                    {
                        string ss = sc.Trim();
                        cl.Add(new Cookie(ss.Split('=')[0].Trim(), ss.Split('=')[1].Trim(), "/"));
                    }
                    cookieCon.Add(new Uri(requestUrl), cl);
                    request.CookieContainer = cookieCon;
                }

                if(Regex.IsMatch(requestUrl, @"(?<=<POST>)[\S\s]*(?=</POST>)", RegexOptions.IgnoreCase))
                {
                    Match s = Regex.Match(requestUrl, @"(?<=<POST>).*(?=</POST>)", RegexOptions.IgnoreCase);
                    string postPara = s.Groups[0].Value.ToString();
                    byte[] pPara = Encoding.ASCII.GetBytes(postPara);

                    request.ContentType = "application/x-www-form-urlencoded";
                    request.ContentLength = pPara.Length;

                    request.Method = "POST";

                    System.IO.Stream reqStream = request.GetRequestStream();
                    reqStream.Write(pPara, 0, pPara.Length);
                    reqStream.Close();
                }
                else
                {
                    request.Method = "GET";
                }

                response = (HttpWebResponse)request.GetResponse();
                System.IO.Stream respStream = response.GetResponseStream();

                reader = new System.IO.StreamReader(respStream, Encoding.UTF8);
                return reader.ReadToEnd();
            }
            catch(Exception ex)
            {
                throw ex;
            }
            finally
            {
                if(response != null)
                    response.Close();
            }
        }
        #endregion
    }

    public class RequestData
    {
        Hashtable hash = new Hashtable();

        public RequestData()
        {

        }

        public string GetData()
        {
            string r = "";

            foreach(string key in hash.Keys)
            {
                if(r.Length > 0)
                    r += "&";
                r += key + "=" + hash[key];
            }

            return r;
        }

        public void AddField(string Field, string Value)
        {
            hash[Field] = Value;
        }
    }
}
